{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "5-conv-draft.ipynb",
      "version": "0.3.2",
      "views": {},
      "default_view": {},
      "provenance": []
    }
  },
  "cells": [
    {
      "metadata": {
        "id": "JguZ3NBZUkpo",
        "colab_type": "text"
      },
      "cell_type": "markdown",
      "source": [
        "# Introduction to Convolutional Neural Networks (convnets or CNNs) with tf.keras, tf.data, and eager execution.\n",
        "\n",
        "For this tutorial we will look at a convnet problem. Like the first tutorial, we will classify MNIST digits. This tutorial was inspired by [this one](https://github.com/fchollet/deep-learning-with-python-notebooks/blob/master/5.1-introduction-to-convnets.ipynb)."
      ]
    },
    {
      "metadata": {
        "id": "qWT31nsxURdJ",
        "colab_type": "code",
        "colab": {
          "autoexec": {
            "startup": false,
            "wait_interval": 0
          }
        }
      },
      "cell_type": "code",
      "source": [
        "!pip install -q -U tensorflow==1.8.0\n",
        "import tensorflow as tf\n",
        "\n",
        "import numpy as np\n",
        "\n",
        "# Enable Eager mode. Re-running this cell will fail. Restart the Runtime to re-enable Eager.\n",
        "tf.enable_eager_execution()"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "metadata": {
        "id": "vNCKRyhQVSWO",
        "colab_type": "code",
        "colab": {
          "autoexec": {
            "startup": false,
            "wait_interval": 0
          }
        }
      },
      "cell_type": "code",
      "source": [
        "(train_images, train_labels), (test_images, test_labels) = tf.keras.datasets.mnist.load_data()"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "metadata": {
        "id": "5eDlt-AnVafg",
        "colab_type": "code",
        "colab": {
          "autoexec": {
            "startup": false,
            "wait_interval": 0
          }
        }
      },
      "cell_type": "code",
      "source": [
        "TRAINING_SIZE = len(train_images)\n",
        "TEST_SIZE = len(test_images)\n",
        "\n",
        "train_images = np.asarray(train_images, dtype=np.float32) / 255\n",
        "\n",
        "# Convert the train images and add channels\n",
        "train_images = train_images.reshape((TRAINING_SIZE, 28, 28, 1))\n",
        "\n",
        "test_images = np.asarray(test_images, dtype=np.float32) / 255\n",
        "# Convert the train images and add channels\n",
        "test_images = test_images.reshape((TEST_SIZE, 28, 28, 1))"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "metadata": {
        "id": "YNi4TNvlVcIB",
        "colab_type": "code",
        "colab": {
          "autoexec": {
            "startup": false,
            "wait_interval": 0
          }
        }
      },
      "cell_type": "code",
      "source": [
        "# How many digits we are predicting from (0-9)\n",
        "LABEL_DIMENSIONS = 10\n",
        "\n",
        "train_labels  = tf.keras.utils.to_categorical(train_labels, LABEL_DIMENSIONS)\n",
        "test_labels = tf.keras.utils.to_categorical(test_labels, LABEL_DIMENSIONS)\n",
        "\n",
        "# Cast the labels to floats, needed later\n",
        "train_labels = train_labels.astype(np.float32)\n",
        "test_labels = test_labels.astype(np.float32)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "metadata": {
        "id": "iHaND5a6Vc-B",
        "colab_type": "code",
        "colab": {
          "autoexec": {
            "startup": false,
            "wait_interval": 0
          }
        }
      },
      "cell_type": "code",
      "source": [
        "model = tf.keras.Sequential()\n",
        "\n",
        "model.add(tf.keras.layers.Conv2D(filters=32, kernel_size=(3, 3), activation=tf.nn.relu, input_shape=(28, 28, 1)))\n",
        "model.add(tf.keras.layers.MaxPooling2D(pool_size=(2, 2), strides=2))\n",
        "model.add(tf.keras.layers.Conv2D(filters=64, kernel_size=(3, 3), activation=tf.nn.relu))\n",
        "model.add(tf.keras.layers.MaxPooling2D(pool_size=(2, 2), strides=2))\n",
        "model.add(tf.keras.layers.Conv2D(filters=64, kernel_size=(3, 3), activation=tf.nn.relu))\n",
        "\n",
        "model.summary()"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "metadata": {
        "id": "8EOBhY6xVd1S",
        "colab_type": "code",
        "colab": {
          "autoexec": {
            "startup": false,
            "wait_interval": 0
          }
        }
      },
      "cell_type": "code",
      "source": [
        "model.add(tf.keras.layers.Flatten())\n",
        "model.add(tf.keras.layers.Dense(64, activation=tf.nn.relu))\n",
        "model.add(tf.keras.layers.Dense(10, activation=tf.nn.softmax))"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "metadata": {
        "id": "SVUAOoeXVfQA",
        "colab_type": "code",
        "colab": {
          "autoexec": {
            "startup": false,
            "wait_interval": 0
          }
        }
      },
      "cell_type": "code",
      "source": [
        "optimizer = tf.train.RMSPropOptimizer(learning_rate=0.001)\n",
        "\n",
        "model.compile(loss='categorical_crossentropy',\n",
        "              optimizer=optimizer,\n",
        "              metrics=['accuracy'])\n",
        "\n",
        "model.summary()"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "metadata": {
        "id": "8jpqP9JYVgxM",
        "colab_type": "code",
        "colab": {
          "autoexec": {
            "startup": false,
            "wait_interval": 0
          }
        }
      },
      "cell_type": "code",
      "source": [
        "BATCH_SIZE=128\n",
        "\n",
        "# Because tf.data may work with potentially **large** collections of data\n",
        "# we do not shuffle the entire dataset by default\n",
        "# Instead, we maintain a buffer of SHUFFLE_SIZE elements\n",
        "# and sample from there.\n",
        "SHUFFLE_SIZE = 10000 \n",
        "\n",
        "# Create the dataset\n",
        "dataset = tf.data.Dataset.from_tensor_slices((train_images, train_labels))\n",
        "dataset = dataset.shuffle(SHUFFLE_SIZE)\n",
        "dataset = dataset.batch(BATCH_SIZE)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "metadata": {
        "id": "jvDEbM1DVigY",
        "colab_type": "code",
        "colab": {
          "autoexec": {
            "startup": false,
            "wait_interval": 0
          }
        }
      },
      "cell_type": "code",
      "source": [
        "EPOCHS=5\n",
        "\n",
        "for epoch in range(EPOCHS):\n",
        "  for (batch, (images, labels)) in enumerate(dataset):\n",
        "    train_loss, train_accuracy = model.train_on_batch(images, labels)\n",
        "    \n",
        "    if batch % 10 == 0: print(batch, train_accuracy)\n",
        "  \n",
        "  # Here you can gather any metrics or adjust your training parameters\n",
        "  print('Epoch #%d\\t Loss: %.6f\\tAccuracy: %.6f' % (epoch + 1, train_loss, train_accuracy))"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "metadata": {
        "id": "O5ddqxgdVzQP",
        "colab_type": "code",
        "colab": {
          "autoexec": {
            "startup": false,
            "wait_interval": 0
          }
        }
      },
      "cell_type": "code",
      "source": [
        "test_loss, test_acc = model.evaluate(test_images, test_labels)\n",
        "print('\\nTest Model \\t\\t Loss: %.6f\\tAccuracy: %.6f' % (test_loss, test_acc))"
      ],
      "execution_count": 0,
      "outputs": []
    }
  ]
}